#pragma once
#include <cppunit/config/SourcePrefix.h>
#include "QueryPreProcessorTest.h"
#include <iostream>
#include <string>
#include <fstream>

using namespace std;

void
QueryPreProcessorTest::setUp()
{}
void
QueryPreProcessorTest::tearDown()
{}

CPPUNIT_TEST_SUITE_REGISTRATION( QueryPreProcessorTest );

void QueryPreProcessorTest::testConstructor() 
{
	PKB* pkb = new PKB();
	qpp = new QueryPreProcessor(pkb);

	
};

void QueryPreProcessorTest::testprocessQuery1() 
{
	PKB* pkb = new PKB();
	qpp = new QueryPreProcessor(pkb);
	cout << "Testing: vector<vector<string>> QueryPreProcessor::processQuery(string)" << endl;
	cout << "Testing: One such that & One pattern" << endl;

	string query = "assign a; Select a such that Parent(5, a) pattern a(_, _\"2+x\"_)";
	vector<vector<string>> parsed = qpp->processQuery(query);
	cout << "- testing synonym and type" << endl;
	CPPUNIT_ASSERT(parsed.at(0).at(0) == "a");
	CPPUNIT_ASSERT(parsed.at(0).at(1) == "assign");
	cout << "Test OK - synonym and type" << endl;

	cout << "- testing parsing such that clause" << endl;
	CPPUNIT_ASSERT(parsed.at(1).at(0) == "such that");
	CPPUNIT_ASSERT(parsed.at(1).at(1) == "Parent");
	CPPUNIT_ASSERT(parsed.at(1).at(2) == "5");
	CPPUNIT_ASSERT(parsed.at(1).at(3) == "a");
	CPPUNIT_ASSERT(parsed.at(1).at(4) == "integer");
	CPPUNIT_ASSERT(parsed.at(1).at(5) == "syn");
	CPPUNIT_ASSERT(parsed.at(1).at(6) == "NULL");
	CPPUNIT_ASSERT(parsed.at(1).at(7) == "assign");
	cout << "Test OK - parsing such that clause" << endl;

	cout << "- testing parsing pattern clause" << endl;
	CPPUNIT_ASSERT(parsed.at(2).at(0) == "pattern");
	CPPUNIT_ASSERT(parsed.at(2).at(1) == "a");
	CPPUNIT_ASSERT(parsed.at(2).at(2) == "assign");
	CPPUNIT_ASSERT(parsed.at(2).at(3) == "");
	CPPUNIT_ASSERT(parsed.at(2).at(4) == "underscore");
	CPPUNIT_ASSERT(parsed.at(2).at(5) == "|2|x|+|");
	CPPUNIT_ASSERT(parsed.at(2).at(6) == "multiple");
	cout << "Testing OK - parsing pattern clause" << endl;

	cout << "Test OK: One such that & One pattern" << endl;
}

void QueryPreProcessorTest::testprocessQueryMultiples() 
{
	PKB* pkb = new PKB();
	qpp = new QueryPreProcessor(pkb);
	cout << "Testing: Three patterns" << endl;
	string pattern, assign, underscore, a, multiple;
	pattern = "pattern";
	assign = "assign";
	a = "a";
	underscore = "underscore";
	multiple = "multiple";

	string query = "assign a; Select a pattern a(_,_\"(h-k-(w*u*r)*(u+i)-(w+i))*r\"_) and pattern a(\"j\",_\"(9)\"_) and pattern a(_,_\"(2*g)\"_)";
	vector<vector<string>> parsed = qpp->processQuery(query);
	cout << "- testing parsing pattern clause" << endl;

	CPPUNIT_ASSERT(parsed.at(0).at(0) == a);
	CPPUNIT_ASSERT(parsed.at(0).at(1) == assign);
	CPPUNIT_ASSERT(parsed.at(0).at(2) == "NULL");
	CPPUNIT_ASSERT(parsed.at(0).at(3) == "FALSE");
	CPPUNIT_ASSERT(parsed.at(1).at(0) == pattern);
	CPPUNIT_ASSERT(parsed.at(1).at(1) == a);
	CPPUNIT_ASSERT(parsed.at(1).at(2) == assign);
	CPPUNIT_ASSERT(parsed.at(1).at(3) == "");
	CPPUNIT_ASSERT(parsed.at(1).at(4) == underscore);
	CPPUNIT_ASSERT(parsed.at(1).at(5) == "|h|k|-|w|u|*|r|*|u|i|+|*|-|w|i|+|-|r|*|");
	CPPUNIT_ASSERT(parsed.at(1).at(6) == multiple);
	CPPUNIT_ASSERT(parsed.at(2).at(0) == pattern);
	CPPUNIT_ASSERT(parsed.at(2).at(1) == a);
	CPPUNIT_ASSERT(parsed.at(2).at(2) == assign);
	CPPUNIT_ASSERT(parsed.at(2).at(3) == "j");
	CPPUNIT_ASSERT(parsed.at(2).at(4) == "ident");
	CPPUNIT_ASSERT(parsed.at(2).at(5) == "|9|");
	CPPUNIT_ASSERT(parsed.at(2).at(6) == multiple);
	CPPUNIT_ASSERT(parsed.at(3).at(0) == pattern);
	CPPUNIT_ASSERT(parsed.at(3).at(1) == a);
	CPPUNIT_ASSERT(parsed.at(3).at(2) == assign);
	CPPUNIT_ASSERT(parsed.at(3).at(3) == "");
	CPPUNIT_ASSERT(parsed.at(3).at(4) == underscore);
	CPPUNIT_ASSERT(parsed.at(3).at(5) == "|2|g|*|");
	CPPUNIT_ASSERT(parsed.at(3).at(6) == multiple);

	cout << "Test OK: Three patterns" << endl;
	cout << "Test OK: vector<vector<string>> QueryPreProcessor::processQuery(string)" << endl;
};